package gov.pbc.gx.nn.pz.bdf.view;

import gov.pbc.gx.nn.pz.bdf.entity.Dept;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;




import com.bstek.bdf2.core.CoreHibernateDao;
import com.bstek.bdf2.core.business.IDept;
import com.bstek.bdf2.core.business.IUser;
import com.bstek.bdf2.core.context.ContextHolder;
import com.bstek.bdf2.core.exception.NoneLoginException;
import com.bstek.bdf2.core.service.IDeptService;
import com.bstek.bdf2.core.service.IGroupService;
import com.bstek.bdf2.core.service.IRoleService;
import com.bstek.bdf2.core.service.MemberType;
import com.bstek.dorado.annotation.DataProvider;
import com.bstek.dorado.annotation.DataResolver;
import com.bstek.dorado.annotation.Expose;
import com.bstek.dorado.data.entity.EntityState;
import com.bstek.dorado.data.entity.EntityUtils;

/**
 * @since 2013-1-29
 * @author Jacky.gao
 */
@Component("deptMaintain")
public class DeptMaintain extends CoreHibernateDao {

	@Autowired
	@Qualifier(IDeptService.BEAN_ID)
	private IDeptService deptService;
	@Autowired
	private IRoleService roleService;
	@Autowired
	@Qualifier(IGroupService.BEAN_ID)
	private IGroupService groupService;

	@DataProvider
	public List<IDept> loadDepts(String parentId) throws Exception {
		IUser user = ContextHolder.getLoginUser();
		if (user == null) {
			throw new NoneLoginException("Please login first");
		}
		String companyId = user.getCompanyId();
		if (StringUtils.isNotEmpty(getFixedCompanyId())) {
			companyId = getFixedCompanyId();
		}
		return deptService.loadDeptsByParentId(parentId, companyId);
	}

	@DataResolver
	public void saveDepts(Collection<Dept> depts) {
		IUser user = ContextHolder.getLoginUser();
		if (user == null) {
			throw new NoneLoginException("Please login first");
		}
		String companyId = user.getCompanyId();
		if (StringUtils.isNotEmpty(getFixedCompanyId())) {
			companyId = getFixedCompanyId();
		}
		Session session = this.getSessionFactory().openSession();
		try {
			for (Dept dept : depts) {
				EntityState state = EntityUtils.getState(dept);

				if (state.equals(EntityState.NEW)) {
					dept.setCompanyId(companyId);
					dept.setCreateDate(new Date());
					String s = UUID.randomUUID().toString();
					dept.setId(s);
					dept.setCode(getCode(dept));
					session.save(dept);
				}
				if (state.equals(EntityState.MODIFIED)
						|| state.equals(EntityState.MOVED)) {
					session.update(dept);
				}

				if (dept.getChildren() != null) {
					Dept[] deptss = new Dept[dept.getChildren().size()];
					saveDepts(Arrays.asList(dept.getChildren().toArray(deptss)));
				}

				if (state.equals(EntityState.DELETED)) {
					if (countChildren(dept.getId()) == 0) {
						roleService.deleteRoleMemeber(dept.getId(),
								MemberType.Dept);
						groupService.deleteGroupMemeber(dept.getId(),
								MemberType.Dept);
						session.delete(dept);
					} else {
						throw new RuntimeException("请先删除子部门");
					}
				}
			}
		} finally {
			session.flush();
			session.close();
		}
	}

	private synchronized String getCode(Dept dept) {

		String code = "";

		if (dept.getParentId() == null) {

			String hql = "select max(d.code) from " + Dept.class.getName()
					+ " d where d.parentId is null ";
			List<String> ls = new ArrayList<String>();
			ls = this.query(hql);
			code = ls.get(0);

			if (code != null) {

				if (Integer.parseInt(code) < 9) {
					code = "00" + (Integer.parseInt(code) + 1);
					return code;
				}

				if (Integer.parseInt(code) < 99) {
					code = "0" + (Integer.parseInt(code) + 1);
					return code;
				}

				if (Integer.parseInt(code) >= 99) {
					code = "" + (Integer.parseInt(code) + 1);
					return code;
				}
			}
			code = "001";
			return code;
		} else {
			String hql = "select max(d.code) from " + Dept.class.getName()
					+ " d where d.parentId = :parentId ";
			Map<String, Object> parameterMap = new HashMap<String, Object>();
			parameterMap.put("parentId", dept.getParentId());
			List<String> ls = this.query(hql, parameterMap);

			String hqls = "select d.code from " + Dept.class.getName()
					+ " d where d.id = :parentId ";
			Map<String, Object> parameterMaps = new HashMap<String, Object>();
			parameterMaps.put("parentId", dept.getParentId());
			List<String> lss = this.query(hqls, parameterMap);

			code = ls.get(0);
			if (StringUtils.isEmpty(code)) {
				code = (lss.get(0) + "001");
				return code;
			} else {

				String codess = code.substring(0, code.length() - 3);
				String codes = code.substring(code.length() - 3);
				String scodes = Integer.toString(Integer.parseInt(codes) + 1);

				// String codes = Integer.toString((Integer.parseInt(code) +
				// 1));
				if (scodes.length() != codes.length()) {
					int nums = codes.length() - scodes.length();
					String k = "";
					for (int i = 0; i < nums; i++) {
						k = k + "0";
					}
					code = codess + k + scodes;
					return code;
				} else {
					return codess + scodes;
				}
			}
		}
	}

	@Expose
	public String uniqueCheck(String id) {
		String hql = "select count(*) from " + Dept.class.getName()
				+ " d where d.id = :id";
		Map<String, Object> parameterMap = new HashMap<String, Object>();
		parameterMap.put("id", id);
		if (this.queryForInt(hql, parameterMap) > 0) {
			return "部门ID已存在！";
		} else {
			return null;
		}
	}

	@Expose
	public int countChildren(String parentId) {
		String hql = "select count(*) from " + Dept.class.getName()
				+ " d where d.parentId = :parentId";
		Map<String, Object> parameterMap = new HashMap<String, Object>();
		parameterMap.put("parentId", parentId);
		return this.queryForInt(hql, parameterMap);
	}

	public IDeptService getDeptService() {
		return deptService;
	}

	public void setDeptService(IDeptService deptService) {
		this.deptService = deptService;
	}

	public IRoleService getRoleService() {
		return roleService;
	}

	public void setRoleService(IRoleService roleService) {
		this.roleService = roleService;
	}

	public IGroupService getGroupService() {
		return groupService;
	}

	public void setGroupService(IGroupService groupService) {
		this.groupService = groupService;
	}
}
